<template>
  <div 
    ref="rootRef" 
    class="tree-root thin-scrollbar scrollbar-compact"
    @keydown="onKeyDown"
    @scroll="onScroll"
    tabindex="0"
  >
    <VirtualList
      ref="virtualListRef"
      :items="effectiveFlatNodes"
      :item-height="rowHeight"
      :overscan="5"
      @scroll="onVirtualScroll"
    >
      <template #default="{ item, index }">
        <TreeNodeRow
          :item="{ ...item, expanded: isExpanded(item.node.id) }"
          :index="index"
          :indent="indent"
          :row-height="rowHeight"
          :selected="selectedIds.has(String(item.node.id))"
          :focused="selectedId === String(item.node.id)"
          :editing-node-id="editingNodeId"
          :editing-mode="editingMode"
          :editing-label="editingLabel"
          :filter-text="filterText"
          :compress-separator="compressSeparator"
          :animate-changes="animateChanges"
          :get-icon="getIcon"
          :draggable="draggable"
          @click="onNodeClick"
          @dblclick="onNodeDoubleClick"
          @contextmenu="onNodeContextMenu"
          @toggle="onNodeToggle"
          @dragstart="onNodeDragStart"
          @dragover="onNodeDragOver"
          @dragleave="onNodeDragLeave"
          @drop="onNodeDrop"
          @dragend="onNodeDragEnd"
          @commit-inline="onCommitInline"
          @cancel-inline="onCancelInline"
          @update:editing-label="(value) => editingLabel.value = value"
          @set-editing-input="setEditingInput"
        />
      </template>
    </VirtualList>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick, shallowRef } from 'vue';
import { openContextMenu } from '../assets/menus';
import { triggerAction } from '../assets/hotkeys';
import VirtualList from './VirtualList.vue';
import TreeNodeRow from './TreeNodeRow.vue';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();

// Props - 与原TreeView保持一致
const props = defineProps({
  root: { type: Object, required: true },
  loadChildren: { type: Function, default: null },
  indent: { type: Number, default: 12 },
  getIcon: { type: Function, default: null },
  showRoot: { type: Boolean, default: true },
  compressFolders: { type: Boolean, default: true },
  filterText: { type: String, default: '' },
  filterFn: { type: Function, default: null },
  enableMultiSelect: { type: Boolean, default: true },
  draggable: { type: Boolean, default: true },
  compressSeparator: { type: String, default: '/' },
  animateChanges: { type: Boolean, default: false },
});

// Events - 与原TreeView保持一致
const emit = defineEmits([
  'open', 'preview', 'selection-change', 
  'dragstart', 'dragover', 'dragleave', 'drop', 'dragend'
]);

// Refs
const rootRef = ref(null);
const virtualListRef = ref(null);

// 核心状态管理
const expanded = ref(new Set());
const selectedId = ref(null);
const selectedIds = ref(new Set());
const lastAnchorIndex = ref(-1);
const rowHeight = 24;
let lastClickTime = 0;
let lastClickId = null;
const scrollTop = ref(0);

// 优化后的索引缓存
const nodeIndex = shallowRef(new Map());
const nodeParentMap = shallowRef(new Map());

// 内联编辑状态
const editingNodeId = ref(null);
const editingMode = ref(null);
const editingLabel = ref('');
const editingParentId = ref(null);
const editingInputEl = ref(null);

// 防抖定时器
let toggleDebounceTimer = null;

// 核心工具函数
function isExpanded(id) { 
  return expanded.value.has(String(id)); 
}

function toggle(node) {
  const id = String(node.id);
  
  // 立即更新UI状态
  if (expanded.value.has(id)) {
    expanded.value.delete(id);
  } else {
    expanded.value.add(id);
  }
  
  // 防抖处理依赖计算
  if (toggleDebounceTimer) {
    clearTimeout(toggleDebounceTimer);
  }
  toggleDebounceTimer = setTimeout(() => {
    // 触发依赖计算属性更新
    expanded.value = new Set(expanded.value);
  }, 16);
}

function getChildren(node) {
  return Array.isArray(node.children) ? node.children : [];
}

async function loadChildrenIfNeeded(node) {
  if (!props.loadChildren) return;
  
  // 检查是否需要加载：未加载过（children === undefined）或者明确标记需要重新加载
  const needsLoading = !Array.isArray(node.children) || (node.__needsReload && Array.isArray(node.children));
  
  if (!needsLoading) return;
  
  try {
    // 添加加载状态标记，防止重复加载
    if (node.__loading) return;
    node.__loading = true;
    
    const kids = await props.loadChildren(node);
    node.children = Array.isArray(kids) ? kids : [];
    
    // 清除重载标记
    delete node.__needsReload;
  } catch (error) {
    console.warn('Failed to load children for node:', node.id, error);
    // 加载失败时设置为空数组，避免无限重试
    node.children = [];
  } finally {
    delete node.__loading;
  }
}

function isDirectory(n) {
  return n && (n.isDir === true || n.is_dir === true || n.isFolder === true);
}

// 扁平化节点计算
const flatNodes = computed(() => {
  const out = [];
  nodeParentMap.value.clear();
  
  function computeCompressedLabelIfAny(n) {
    if (!props.compressFolders) return null;
    const rootId = String(n.id);
    if (expanded.value.has(rootId)) return null;
    if (!isDirectory(n)) return null;
    const parts = [String(n.label ?? '')];
    let current = n;
    
    while (true) {
      const kids = getChildren(current);
      if (!Array.isArray(kids) || kids.length !== 1) break;
      const only = kids[0];
      if (!isDirectory(only)) break;
      parts.push(String(only.label ?? ''));
      current = only;
      if (expanded.value.has(String(current.id))) break;
    }
    if (parts.length <= 1) return null;
    return parts.join('/');
  }
  
  function pushNode(n, depth) {
    if (!n) return;
    nodeIndex.value.set(String(n.id), n);
    const compressed = computeCompressedLabelIfAny(n);
    const id = `${n.id}-${out.length}`;
    out.push({ 
      node: n, 
      depth, 
      displayLabel: compressed || String(n.label ?? ''),
      id
    });
    
    const isDir = n.isDir === true || n.is_dir === true || n.isFolder === true;
    if (!isDir) return;
    const nodeId = String(n.id);
    if (!expanded.value.has(nodeId)) return;
    const children = getChildren(n);
    if (!Array.isArray(children) || children.length === 0) return;
    
    for (const c of children) {
      nodeParentMap.value.set(String(c.id), String(n.id));
      pushNode(c, depth + 1);
    }
  }
  
  if (!props.root) return out;
  if (props.showRoot) {
    pushNode(props.root, 0);
  } else {
    const kids = getChildren(props.root);
    for (const c of kids) {
      nodeParentMap.value.set(String(c.id), String(props.root.id));
      pushNode(c, 0);
    }
  }
  return out;
});

// 过滤后的节点
const effectiveFlatNodes = computed(() => {
  const q = String(props.filterText || '').trim().toLowerCase();
  const matcher = props.filterFn || ((n) => String(n.label || '').toLowerCase().includes(q));
  if (!q) return flatNodes.value;
  
  nodeParentMap.value.clear();
  const include = new Set();
  
  function dfsMark(n) {
    if (!n) return false;
    const kids = getChildren(n);
    let matched = false;
    if (matcher(n)) matched = true;
    if (Array.isArray(kids)) {
      for (const c of kids) {
        if (dfsMark(c)) {
          include.add(String(n.id));
          matched = true;
        }
      }
    }
    if (matched) include.add(String(n.id));
    return matched;
  }
  
  if (props.root) dfsMark(props.root);
  
  const out = [];
  function pushAll(n, depth, parentId) {
    if (!n) return;
    const id = String(n.id);
    if (!include.has(id)) return;
    if (parentId != null) nodeParentMap.value.set(id, String(parentId));
    
    const display = (function() {
      const isDir = n.isDir === true || n.is_dir === true || n.isFolder === true;
      if (!isDir) return String(n.label ?? '');
      const kids = getChildren(n);
      if (!Array.isArray(kids) || kids.length !== 1) return String(n.label ?? '');
      
      const parts = [String(n.label ?? '')];
      let cur = n;
      while (true) {
        const k = getChildren(cur);
        if (!Array.isArray(k) || k.length !== 1) break;
        const only = k[0];
        if (!isDirectory(only)) break;
        parts.push(String(only.label ?? ''));
        cur = only;
      }
      return parts.join(props.compressSeparator || '/');
    })();
    
    nodeIndex.value.set(String(n.id), n);
    const itemId = `${n.id}-${out.length}`;
    out.push({ 
      node: n, 
      depth, 
      displayLabel: display,
      id: itemId
    });
    
    const kids = getChildren(n);
    if (Array.isArray(kids)) {
      for (const c of kids) pushAll(c, depth + 1, id);
    }
  }
  
  if (props.root) {
    if (props.showRoot) {
      pushAll(props.root, 0);
    } else {
      for (const c of getChildren(props.root) || []) {
        pushAll(c, 0, props.root.id);
      }
    }
  }
  return out;
});

// 索引映射
const indexById = computed(() => {
  const map = new Map();
  const arr = effectiveFlatNodes.value;
  for (let i = 0; i < arr.length; i++) {
    map.set(String(arr[i]?.node?.id), i);
  }
  return map;
});

// 事件处理器
function onNodeClick(item, event) {
  select(item.node, event);
}

function onNodeDoubleClick(item, event) {
  const node = item.node;
  const isDir = isDirectory(node);
  if (isDir) {
    toggle(node);
  } else {
    emit('open', node);
  }
}

function onNodeContextMenu(item, event) {
  select(item.node, event, { context: true });
}

function onNodeToggle(item) {
  toggle(item.node);
}

function onNodeDragStart(item, event) {
  emit('dragstart', item.node, event);
}

function onNodeDragOver(item, event) {
  emit('dragover', item.node, event);
}

function onNodeDragLeave(item, event) {
  emit('dragleave', item.node, event);
}

function onNodeDrop(item, event) {
  emit('drop', item.node, event);
}

function onNodeDragEnd(item, event) {
  emit('dragend', item.node, event);
}

// 选择逻辑
function select(node, e, extra) {
  const idx = findIndexById(node.id);
  const isDir = node.isDir === true || node.is_dir === true || node.isFolder === true;
  
  // 上下文菜单
  if (extra?.context && e) {
    selectedId.value = String(node.id);
    if (!props.enableMultiSelect || (!e.ctrlKey && !e.metaKey && !e.shiftKey)) {
      selectedIds.value = new Set([String(node.id)]);
      lastAnchorIndex.value = idx;
      emit('selection-change', Array.from(selectedIds.value));
    }
    const at = { x: e.clientX, y: e.clientY };
    openContextMenu({ use: 'explorer.context' }, at, { node, selectedIds: Array.from(selectedIds.value) });
    return;
  }
  
  // 点击选择（支持多选）
  if (e && e.type === 'click') {
    const sid = String(node.id);
    
    if (props.enableMultiSelect && e.shiftKey && lastAnchorIndex.value >= 0) {
      const cur = idx >= 0 ? idx : 0;
      const start = Math.min(lastAnchorIndex.value, cur);
      const end = Math.max(lastAnchorIndex.value, cur);
      const arr = effectiveFlatNodes.value;
      const set = new Set(selectedIds.value);
      for (let i = start; i <= end; i++) {
        set.add(String(arr[i]?.node?.id));
      }
      selectedIds.value = set;
      selectedId.value = sid;
      emit('selection-change', Array.from(selectedIds.value));
    } else if (props.enableMultiSelect && (e.ctrlKey || e.metaKey)) {
      const set = new Set(selectedIds.value);
      if (set.has(sid)) set.delete(sid); else set.add(sid);
      selectedIds.value = set;
      selectedId.value = sid;
      lastAnchorIndex.value = idx;
      emit('selection-change', Array.from(selectedIds.value));
    } else {
      selectedIds.value = new Set([sid]);
      selectedId.value = sid;
      lastAnchorIndex.value = idx;
      emit('selection-change', Array.from(selectedIds.value));
    }
    
    // 单击目录：展开压缩链或切换
    if (isDir && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
      Promise.resolve(expandOrToggleDir(node, !!e.altKey));
    }
    
    lastClickTime = Date.now();
    lastClickId = sid;
  }
}

// 工具函数
function findIndexById(id) {
  return indexById.value.get(String(id)) ?? -1;
}

function findNodeById(id) {
  return nodeIndex.value.get(String(id)) ?? null;
}

async function expandOrToggleDir(node, forceToggle = false) {
  const id = String(node.id);
  if (forceToggle) {
    toggle(node);
    return;
  }
  
  if (!expanded.value.has(id)) {
    await loadChildrenIfNeeded(node);
    expanded.value.add(id);
  } else {
    expanded.value.delete(id);
  }
}

// 内联编辑
function setEditingInput(el) {
  editingInputEl.value = el;
  if (el) {
    nextTick(() => {
      el.focus();
      el.select();
    });
  }
}

function onCommitInline() {
  emit('commit-inline');
}

function onCancelInline() {
  emit('cancel-inline');
}

// 键盘导航和滚动
function onKeyDown(e) {
  // 键盘导航逻辑保持与原TreeView一致
  // 这里简化处理，实际应该包含完整的键盘导航逻辑
}

function onScroll(e) {
  scrollTop.value = e.target.scrollTop;
}

function onVirtualScroll(scrollTop) {
  // 处理虚拟滚动事件
}

// 生命周期
onMounted(async () => {
  if (props.root && props.loadChildren) {
    await loadChildrenIfNeeded(props.root);
  }
});

// 监听器
watch(() => props.root, () => {
  nodeIndex.value.clear();
  nodeParentMap.value.clear();
}, { deep: true });

// 暴露给父组件的方法
defineExpose({
  toggle,
  select,
  findNodeById,
  findIndexById,
  expandOrToggleDir,
  setEditingInput
});
</script>

<style scoped>
.tree-root {
  height: 100%;
  overflow: auto;
  outline: none;
}
</style>